package com.by.ai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.by.ai.dto.*;
import com.by.ai.service.LogAnalysisService;
import com.by.log.entity.LogEntity;
import com.by.log.mapper.LogMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class LogAnalysisServiceImpl implements LogAnalysisService {

    private final ChatClient chatClient;
    @Autowired
    LogMapper logMapper;

    @Override
    public LogAnalysisResponse analyzeLog(LogAnalysisRequest request) {
        LogAnalysisResponse response = new LogAnalysisResponse();
        response.setAnalysisType(request.getAnalysisType());
        response.setAnalysisTime(LocalDateTime.now());

        try {
            switch (request.getAnalysisType()) {
                case "REQUEST_COUNT":
                    RequestCountAnalysis requestAnalysis = analyzeRequestCount(
                            request.getStartTime(), request.getEndTime(), request.getServiceName());
                    response = buildResponseFromRequestAnalysis(requestAnalysis);
                    break;

                case "TRAFFIC":
                    TrafficAnalysis trafficAnalysis = analyzeTraffic(
                            request.getStartTime(), request.getEndTime(), request.getServiceName());
                    response = buildResponseFromTrafficAnalysis(trafficAnalysis);
                    break;

                case "ERROR_TRACKING":
                    ErrorTrackingAnalysis errorAnalysis = analyzeErrors(
                            request.getStartTime(), request.getEndTime(), request.getServiceName());
                    response = buildResponseFromErrorAnalysis(errorAnalysis);
                    break;

                default:
                    // 综合分析
                    response = performComprehensiveAnalysis(request);
            }

            // 使用AI生成洞察和建议
            response = enhanceWithAIInsights(response, request);

        } catch (Exception e) {
            log.error("日志分析失败", e);
            response.setSummary("分析过程中发生错误: " + e.getMessage());
        }

        return response;
    }

    @Override
    public RequestCountAnalysis analyzeRequestCount(LocalDateTime startTime, LocalDateTime endTime, String serviceName) {
        QueryWrapper<LogEntity> wrapper = new QueryWrapper<>();
        wrapper.between("timestamp", startTime, endTime);
        if (serviceName != null) {
            wrapper.eq("service_name", serviceName);
        }
        wrapper.like("message", "HTTP");

        List<LogEntity> logs = logMapper.selectList(wrapper);

        RequestCountAnalysis analysis = new RequestCountAnalysis();
        analysis.setTotalRequests((long) logs.size());

        // 按端点统计请求量
        Map<String, Long> requestsByEndpoint = logs.stream()
                .collect(Collectors.groupingBy(
                        log -> extractEndpoint(log.getMessage()),
                        Collectors.counting()
                ));
        analysis.setRequestsByEndpoint(requestsByEndpoint);

        // 按小时统计请求量
        Map<String, Long> requestsByHour = logs.stream()
                .collect(Collectors.groupingBy(
                        log -> log.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH")),
                        Collectors.counting()
                ));
        analysis.setRequestsByHour(requestsByHour);

        // 计算平均每分钟请求量
        long minutes = java.time.Duration.between(startTime, endTime).toMinutes();
        analysis.setAverageRequestsPerMinute(minutes > 0 ? (double) logs.size() / minutes : 0.0);

        // 找出峰值小时
        analysis.setPeakHour(requestsByHour.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse("N/A"));

        return analysis;
    }

    @Override
    public TrafficAnalysis analyzeTraffic(LocalDateTime startTime, LocalDateTime endTime, String serviceName) {
        QueryWrapper<LogEntity> wrapper = new QueryWrapper<>();
        wrapper.between("timestamp", startTime, endTime);
        if (serviceName != null) {
            wrapper.eq("service_name", serviceName);
        }

        List<LogEntity> logs = logMapper.selectList(wrapper);

        TrafficAnalysis analysis = new TrafficAnalysis();
        analysis.setTotalTraffic((long) logs.size());

        // 按服务统计流量
        Map<String, Long> trafficByService = logs.stream()
                .collect(Collectors.groupingBy(
                        LogEntity::getServiceName,
                        Collectors.counting()
                ));
        analysis.setTrafficByService(trafficByService);

        // 响应时间统计 (从日志消息中提取)
        Map<String, Double> responseTimeStats = new HashMap<>();
        List<Double> responseTimes = logs.stream()
                .map(log -> extractResponseTime(log.getMessage()))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (!responseTimes.isEmpty()) {
            responseTimeStats.put("average", responseTimes.stream().mapToDouble(Double::doubleValue).average().orElse(0.0));
            responseTimeStats.put("max", responseTimes.stream().mapToDouble(Double::doubleValue).max().orElse(0.0));
            responseTimeStats.put("min", responseTimes.stream().mapToDouble(Double::doubleValue).min().orElse(0.0));
            analysis.setAverageResponseTime(responseTimeStats.get("average"));
        }
        analysis.setResponseTimeStats(responseTimeStats);

        // 找出最慢的端点
        Map<String, Double> endpointResponseTimes = logs.stream()
                .filter(log -> extractResponseTime(log.getMessage()) != null)
                .collect(Collectors.groupingBy(
                        log -> extractEndpoint(log.getMessage()),
                        Collectors.averagingDouble(log -> extractResponseTime(log.getMessage()))
                ));

        List<String> slowestEndpoints = endpointResponseTimes.entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
                .limit(5)
                .map(entry -> entry.getKey() + " (" + String.format("%.2f", entry.getValue()) + "ms)")
                .collect(Collectors.toList());
        analysis.setSlowestEndpoints(slowestEndpoints);

        return analysis;
    }

    @Override
    public ErrorTrackingAnalysis analyzeErrors(LocalDateTime startTime, LocalDateTime endTime, String serviceName) {
        QueryWrapper<LogEntity> wrapper = new QueryWrapper<>();
        wrapper.between("timestamp", startTime, endTime);
        if (serviceName != null) {
            wrapper.eq("service_name", serviceName);
        }
        wrapper.in("level", Arrays.asList("ERROR", "WARN"));

        List<LogEntity> errorLogs = logMapper.selectList(wrapper);

        ErrorTrackingAnalysis analysis = new ErrorTrackingAnalysis();
        analysis.setTotalErrors((long) errorLogs.size());

        // 按错误类型统计
        Map<String, Long> errorsByType = errorLogs.stream()
                .collect(Collectors.groupingBy(
                        log -> extractErrorType(log.getMessage(), log.getThrowable()),
                        Collectors.counting()
                ));
        analysis.setErrorsByType(errorsByType);

        // 按服务统计错误
        Map<String, Long> errorsByService = errorLogs.stream()
                .collect(Collectors.groupingBy(
                        LogEntity::getServiceName,
                        Collectors.counting()
                ));
        analysis.setErrorsByService(errorsByService);

        // 分析错误模式
        List<ErrorPattern> errorPatterns = analyzeErrorPatterns(errorLogs);
        analysis.setErrorPatterns(errorPatterns);

        // 识别关键错误
        List<String> criticalErrors = errorLogs.stream()
                .filter(log -> "ERROR".equals(log.getLevel()))
                .filter(log -> log.getThrowable() != null)
                .map(log -> log.getClassName() + "." + log.getMethodName() + ": " +
                        (log.getThrowable().length() > 100 ?
                                log.getThrowable().substring(0, 100) + "..." :
                                log.getThrowable()))
                .distinct()
                .limit(10)
                .collect(Collectors.toList());
        analysis.setCriticalErrors(criticalErrors);

        return analysis;
    }

    @Override
    public List<String> detectAnomalies(LocalDateTime startTime, LocalDateTime endTime) {
        List<String> anomalies = new ArrayList<>();

        // 检测请求量异常
        RequestCountAnalysis requestAnalysis = analyzeRequestCount(startTime, endTime, null);
        if (requestAnalysis.getAverageRequestsPerMinute() > 1000) {
            anomalies.add("检测到异常高的请求量: " + String.format("%.2f", requestAnalysis.getAverageRequestsPerMinute()) + " 请求/分钟");
        }

        // 检测错误率异常
        ErrorTrackingAnalysis errorAnalysis = analyzeErrors(startTime, endTime, null);
        TrafficAnalysis trafficAnalysis = analyzeTraffic(startTime, endTime, null);

        if (trafficAnalysis.getTotalTraffic() > 0) {
            double errorRate = (double) errorAnalysis.getTotalErrors() / trafficAnalysis.getTotalTraffic() * 100;
            if (errorRate > 5.0) {
                anomalies.add("检测到异常高的错误率: " + String.format("%.2f", errorRate) + "%");
            }
        }

        // 检测响应时间异常
        if (trafficAnalysis.getAverageResponseTime() != null && trafficAnalysis.getAverageResponseTime() > 5000) {
            anomalies.add("检测到异常慢的响应时间: " + String.format("%.2f", trafficAnalysis.getAverageResponseTime()) + "ms");
        }

        return anomalies;
    }

    // 私有辅助方法
    private String extractEndpoint(String message) {
        // 从日志消息中提取端点信息，简化实现
        if (message.contains("GET")) return "GET " + extractPath(message);
        if (message.contains("POST")) return "POST " + extractPath(message);
        if (message.contains("PUT")) return "PUT " + extractPath(message);
        if (message.contains("DELETE")) return "DELETE " + extractPath(message);
        return "UNKNOWN";
    }

    private String extractPath(String message) {
        // 简化的路径提取逻辑
        int start = message.indexOf("/");
        if (start == -1) return "/unknown";
        int end = message.indexOf(" ", start);
        return end == -1 ? message.substring(start) : message.substring(start, end);
    }

    private Double extractResponseTime(String message) {
        // 从日志消息中提取响应时间，假设格式为 "... took 123ms"
        try {
            if (message.contains("took") && message.contains("ms")) {
                int start = message.indexOf("took") + 5;
                int end = message.indexOf("ms", start);
                return Double.parseDouble(message.substring(start, end).trim());
            }
        } catch (Exception e) {
            // 忽略解析错误
        }
        return null;
    }

    private String extractErrorType(String message, String throwable) {
        if (throwable != null && !throwable.isEmpty()) {
            int colonIndex = throwable.indexOf(":");
            return colonIndex > 0 ? throwable.substring(0, colonIndex) : throwable;
        }

        if (message.contains("Exception")) {
            int start = message.indexOf("Exception") - 20;
            int end = message.indexOf("Exception") + 9;
            start = Math.max(0, start);
            return message.substring(start, Math.min(message.length(), end)).trim();
        }

        return "Unknown Error";
    }

    private List<ErrorPattern> analyzeErrorPatterns(List<LogEntity> errorLogs) {
        Map<String, List<LogEntity>> groupedErrors = errorLogs.stream()
                .collect(Collectors.groupingBy(log -> extractErrorType(log.getMessage(), log.getThrowable())));

        return groupedErrors.entrySet().stream()
                .map(entry -> {
                    ErrorPattern pattern = new ErrorPattern();
                    pattern.setErrorType(entry.getKey());
                    pattern.setFrequency((long) entry.getValue().size());
                    pattern.setPattern(findCommonPattern(entry.getValue()));
                    pattern.setSuggestedSolution(generateSolution(entry.getKey()));
                    return pattern;
                })
                .sorted((a, b) -> Long.compare(b.getFrequency(), a.getFrequency()))
                .limit(10)
                .collect(Collectors.toList());
    }

    private String findCommonPattern(List<LogEntity> logs) {
        // 简化的模式识别
        Map<String, Long> methodFreq = logs.stream()
                .collect(Collectors.groupingBy(LogEntity::getMethodName, Collectors.counting()));

        return methodFreq.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(entry -> "主要发生在方法: " + entry.getKey() + " (出现 " + entry.getValue() + " 次)")
                .orElse("无明显模式");
    }

    private String generateSolution(String errorType) {
        // 简化的解决方案生成
        if (errorType.contains("NullPointerException")) {
            return "检查空值判断，使用Optional或添加null检查";
        } else if (errorType.contains("TimeoutException")) {
            return "检查网络连接，增加超时时间或优化查询";
        } else if (errorType.contains("SQLException")) {
            return "检查数据库连接，优化SQL查询或检查数据完整性";
        }
        return "请检查相关代码逻辑和系统配置";
    }

    private LogAnalysisResponse buildResponseFromRequestAnalysis(RequestCountAnalysis analysis) {
        LogAnalysisResponse response = new LogAnalysisResponse();
        response.setAnalysisType("REQUEST_COUNT");
        response.setSummary("请求量分析完成，总请求数: " + analysis.getTotalRequests());

        Map<String, Object> data = new HashMap<>();
        data.put("analysis", analysis);
        response.setData(data);

        return response;
    }

    private LogAnalysisResponse buildResponseFromTrafficAnalysis(TrafficAnalysis analysis) {
        LogAnalysisResponse response = new LogAnalysisResponse();
        response.setAnalysisType("TRAFFIC");
        response.setSummary("流量分析完成，总流量: " + analysis.getTotalTraffic());

        Map<String, Object> data = new HashMap<>();
        data.put("analysis", analysis);
        response.setData(data);

        return response;
    }

    private LogAnalysisResponse buildResponseFromErrorAnalysis(ErrorTrackingAnalysis analysis) {
        LogAnalysisResponse response = new LogAnalysisResponse();
        response.setAnalysisType("ERROR_TRACKING");
        response.setSummary("错误分析完成，总错误数: " + analysis.getTotalErrors());

        Map<String, Object> data = new HashMap<>();
        data.put("analysis", analysis);
        response.setData(data);

        return response;
    }

    private LogAnalysisResponse performComprehensiveAnalysis(LogAnalysisRequest request) {
        LogAnalysisResponse response = new LogAnalysisResponse();
        response.setAnalysisType("COMPREHENSIVE");

        RequestCountAnalysis requestAnalysis = analyzeRequestCount(request.getStartTime(), request.getEndTime(), request.getServiceName());
        TrafficAnalysis trafficAnalysis = analyzeTraffic(request.getStartTime(), request.getEndTime(), request.getServiceName());
        ErrorTrackingAnalysis errorAnalysis = analyzeErrors(request.getStartTime(), request.getEndTime(), request.getServiceName());

        Map<String, Object> data = new HashMap<>();
        data.put("requestAnalysis", requestAnalysis);
        data.put("trafficAnalysis", trafficAnalysis);
        data.put("errorAnalysis", errorAnalysis);
        response.setData(data);

        response.setSummary(String.format("综合分析完成 - 请求: %d, 流量: %d, 错误: %d",
                requestAnalysis.getTotalRequests(),
                trafficAnalysis.getTotalTraffic(),
                errorAnalysis.getTotalErrors()));

        return response;
    }

    private LogAnalysisResponse enhanceWithAIInsights(LogAnalysisResponse response, LogAnalysisRequest request) {
        try {
            String promptText = buildAnalysisPrompt(response, request);

            String aiResponse = chatClient.prompt()
                    .user(promptText)
                    .call()
                    .content();

            // 解析AI响应，提取洞察和建议
            String[] parts = aiResponse.split("###");
            List<String> insights = new ArrayList<>();
            List<String> recommendations = new ArrayList<>();

            for (String part : parts) {
                if (part.trim().startsWith("洞察")) {
                    insights.addAll(Arrays.asList(part.split("\n")).stream()
                            .filter(line -> line.trim().startsWith("-") || line.trim().startsWith("•"))
                            .map(line -> line.trim().substring(1).trim())
                            .collect(Collectors.toList()));
                } else if (part.trim().startsWith("建议")) {
                    recommendations.addAll(Arrays.asList(part.split("\n")).stream()
                            .filter(line -> line.trim().startsWith("-") || line.trim().startsWith("•"))
                            .map(line -> line.trim().substring(1).trim())
                            .collect(Collectors.toList()));
                }
            }

            response.setInsights(insights.isEmpty() ? generateDefaultInsights(response) : insights);
            response.setRecommendations(recommendations.isEmpty() ? generateDefaultRecommendations(response) : recommendations);

        } catch (Exception e) {
            log.warn("AI增强分析失败，使用默认洞察", e);
            response.setInsights(generateDefaultInsights(response));
            response.setRecommendations(generateDefaultRecommendations(response));
        }

        return response;
    }

    private String buildAnalysisPrompt(LogAnalysisResponse response, LogAnalysisRequest request) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("作为一名资深的系统运维专家，请分析以下日志数据并提供专业的洞察和建议：\n\n");
        prompt.append("分析类型: ").append(response.getAnalysisType()).append("\n");
        prompt.append("时间范围: ").append(request.getStartTime()).append(" 到 ").append(request.getEndTime()).append("\n");

        if (request.getServiceName() != null) {
            prompt.append("服务名称: ").append(request.getServiceName()).append("\n");
        }

        prompt.append("分析摘要: ").append(response.getSummary()).append("\n\n");

        // 根据分析类型添加具体数据
        Map<String, Object> data = response.getData();
        if (data != null) {
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                prompt.append(entry.getKey()).append(": ").append(entry.getValue().toString()).append("\n");
            }
        }

        prompt.append("\n请提供：\n");
        prompt.append("### 洞察\n");
        prompt.append("- 对当前系统状态的分析\n");
        prompt.append("- 识别的关键模式和趋势\n");
        prompt.append("- 潜在的风险点\n\n");
        prompt.append("### 建议\n");
        prompt.append("- 性能优化建议\n");
        prompt.append("- 错误处理改进\n");
        prompt.append("- 监控和告警策略\n");

        return prompt.toString();
    }

    private List<String> generateDefaultInsights(LogAnalysisResponse response) {
        List<String> insights = new ArrayList<>();

        if ("REQUEST_COUNT".equals(response.getAnalysisType())) {
            insights.add("系统请求量处于正常范围内");
            insights.add("建议继续监控流量变化趋势");
        } else if ("TRAFFIC".equals(response.getAnalysisType())) {
            insights.add("流量分布相对均匀");
            insights.add("响应时间表现良好");
        } else if ("ERROR_TRACKING".equals(response.getAnalysisType())) {
            insights.add("错误数量需要关注");
            insights.add("建议重点关注高频错误类型");
        }

        return insights;
    }

    private List<String> generateDefaultRecommendations(LogAnalysisResponse response) {
        List<String> recommendations = new ArrayList<>();

        recommendations.add("建立自动化监控告警机制");
        recommendations.add("定期进行性能基线评估");
        recommendations.add("优化高频接口的性能表现");
        recommendations.add("建立错误处理和恢复机制");

        return recommendations;
    }
}
